﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Subgurim.Controles;
using ControlLogNamespace;
using System.Drawing;
using System.Collections;
using ControlGeograficoNamespace;
using System.Threading;
using ControlDbNamespace;


namespace ControlHorsetrackNamespace
{

    public delegate void delegEvaluacionEventos(Caballo objCaballo);

    #region CONTROL HORSETRACK
    public class ControlHorsetrack
    {
        public static void evaluacionEventos(Caballo objCaballo)
        {
            ControlDB objConnection = new ControlDB();

            #region Averiguar eventos a evaluar del caballo
            ControlLog.writeLog("[evaluacionEventos] Buscando evaluaciones posibles para el caballo "+objCaballo.strNombre+"("+objCaballo.strIDCaballo+")");
            try
            {
                Cliente objDueno=objConnection.obtenerDuenoDeCaballo(objCaballo);
                foreach(TipoEvento objTipoEvento in objConnection.obtenerEvaluacionesDelCaballo(objCaballo))
                {
                    Evento objEvento;
                    #region Procesar Evento
                    try
                    {
                        objEvento = new Evento(objCaballo, objTipoEvento, objDueno);
                        
                    }
                    catch(Exception ex)
                    {
                        ControlLog.writeLog("[evaluacionEventos] Excepcion procesando evento"+ex.Message);
                        continue;
                    }
                    #endregion

                    #region Agregar Evento Disponible
                    try
                    {
                        objConnection.agregarEventoDisponible(objEvento);
                    }
                    catch(Exception ex)
                    {
                        ControlLog.writeLog("[evaluacionEventos] Excepcion agregando a DB el evento procesado" + ex.Message);
                    }
                    #endregion
                }
            }
            catch(Exception ex)
            {
                ControlLog.writeLog("[evaluacionEventos] Excepcion obteniendo los eventos de evaluacion del caballo "+objCaballo.strNombre+"("+objCaballo.strIDCaballo+"):"+ex.Message);
                throw ex;
            }
            #endregion
        
        }
        /// <summary>
        /// Arma el recuadro de texto cuando se hace click sobre un caballo.
        /// </summary>
        /// <param name="objCaballo">Información del caballo a utilizar</param>
        /// <param name="objTraza">Trazabilidad del caballo o null si no se muestra trazabilidad</param>
        /// <returns>Devuelve un string HTML que debe ser incorporado a la ventana de informacion</returns>
        public static string obtenerCuadroDeTextoDeCaballos(Caballo objCaballo, Trazabilidad objTraza)
        {
            string strCuadroDeInfo = "<center>";
            strCuadroDeInfo += "<table style='background-image:url();font-size:11px ;'>";
            strCuadroDeInfo += "<tr>";
                strCuadroDeInfo += "<td>" + objCaballo.strNombre + "</td>";
                if (objTraza == null)
                {
                    strCuadroDeInfo += "<td><input type=\"button\" style=\"font-size:11px;\" id=\"inputVerUltimosPasos\" value=\"Ver ultimos pasos\" onclick=\"var ev = new serverEvent('showHorseTrack', subgurim_GMap1); ev.addArg('" + objCaballo.strIDCaballo + "');ev.send();if(document.getElementById('inputVerUltimosPasos').value == 'Ver ultimos pasos'){document.getElementById('inputVerUltimosPasos').value='Ocultar ultimos pasos'; }else{document.getElementById('inputVerUltimosPasos').value='Ver ultimos pasos';} \" /></td>";
                }
                else
                {
                    strCuadroDeInfo += "<td><input type=\"button\" style=\"font-size:11px;\" id=\"inputVerUltimosPasos\" value=\"Ocultar ultimos pasos\" onclick=\"var ev = new serverEvent('showHorseTrack', subgurim_GMap1); ev.addArg('" + objCaballo.strIDCaballo + "');ev.send();if(document.getElementById('inputVerUltimosPasos').value == 'Ver ultimos pasos'){document.getElementById('inputVerUltimosPasos').value='Ocultar ultimos pasos'; }else{document.getElementById('inputVerUltimosPasos').value='Ver ultimos pasos';} \" /></td>";
                }
                
            strCuadroDeInfo += "</tr>";
            strCuadroDeInfo += "<tr>";
                strCuadroDeInfo += "<td><img src='Iconos/CaballoIcon.jpg' width='80px' height='70px'></td>";
                strCuadroDeInfo += "<td align='left'style='font-size:11px ;'><b>Raza: </b>" + objCaballo.getRaza() + "</br><b>Categor&iacute;a: </b>" + objCaballo.getCategoria() + "</br><b>Disciplina: </b>" + objCaballo.getDisciplina() + "</br><b>Estado: </b>" + objCaballo.getEstado() + "</br></td>";
            strCuadroDeInfo += "</tr>";
            strCuadroDeInfo += "</table>";
            strCuadroDeInfo += "</center>";

            return strCuadroDeInfo;
        }
    }
    #endregion

    #region OPERADOR
    public enum Operador
    {
        Nextel,
        Claro,
        Personal,
        Movistar,
        OperadorDesconocido
    }
    #endregion
    
    #region TRAZABILIDAD
    public class Trazabilidad
    {
        int inIDTrazabilidad_;

        #region Properties
        private List<GLatLng> lstCaminoRealizadoPorCoordenadas;
        private List<Segmento> lstCaminoRealizadoPorSegmentos;
        private GPolyline objPolyline;
        #endregion
        #region Constructor
        public Trazabilidad()
        {
            lstCaminoRealizadoPorCoordenadas = new List<GLatLng>();
            lstCaminoRealizadoPorSegmentos = new List<Segmento>();
        }
        #endregion
        #region Methods
        
        //// EL AGREGAR tRAZABILIDAD en DB DEBERIA SER UN METODO DE TRAZABILIDAD//FD 14-8-12
        public int inIDTrazabilidad
        { 
            get
            {
                return inIDTrazabilidad_;
            }
            set
            {
                inIDTrazabilidad = value;
            }
        }

        public void dibujarEn(GMap GMap1, IPolygonAction interfaceAccion)
        {
          
            objPolyline = new GPolyline(lstCaminoRealizadoPorCoordenadas);
            objPolyline.clickable = true;
            GMap1.addPolyline(objPolyline);
            ControlLog.writeLog("[Trazabilidad:dibujarEn] Dibujando traza de " + lstCaminoRealizadoPorCoordenadas.Count().ToString() + " pasos. " + this.ToString());
            GMap1.addListener(interfaceAccion.agregarEvento(this));

        }
        public GPolyline getTraza()
        {
            return objPolyline;
        }             
        public void agregarCoordenadas(double dbLatitud, double dbLongitud)
        {
            GLatLng objCoordenada = new GLatLng(dbLatitud, dbLongitud);
            lstCaminoRealizadoPorCoordenadas.Add(objCoordenada);
        }
        public void agregarCoordenadas(GLatLng objCoordenada)
        {
            lstCaminoRealizadoPorCoordenadas.Add(objCoordenada); ;
        }
        public List<GLatLng> obtenerTrazadoEnCoordenadas()
        {
            return lstCaminoRealizadoPorCoordenadas;
        }
        public List<Segmento> obtenerTrazadoEnSegmentos()
        {
            return lstCaminoRealizadoPorSegmentos;
        }
        public void convertirASegmentos()
        {


            if (lstCaminoRealizadoPorCoordenadas.Count < 2)
            {
                throw new Exception("No alcanzan los puntos para armar al menos un segmento. Cantidad de coordenadas=" + lstCaminoRealizadoPorCoordenadas.Count.ToString());
            }

            try
            {
                for (int i = 0; i < (lstCaminoRealizadoPorCoordenadas.Count - 1); i++)
                {
                    Segmento objSegmentoAAgregar = new Segmento(lstCaminoRealizadoPorCoordenadas[i], lstCaminoRealizadoPorCoordenadas[i + 1]);
                    lstCaminoRealizadoPorSegmentos.Add(objSegmentoAAgregar);
                }
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[Trazabilidad:convertirASegmentos] Excepcion convirtiendo a segmento: "+ex.Message);
            }

       
        }        
        public override string ToString()
        {
            string strReturn = "";
            foreach (GLatLng objLatLng in lstCaminoRealizadoPorCoordenadas)
            {
                strReturn += "Latitud: " + objLatLng.lat.ToString() + " Longitud: " + objLatLng.lng.ToString() +" - ";
            }

            return strReturn;
        }
        public string obtenerCantidadDePasos()
        {
            return lstCaminoRealizadoPorCoordenadas.Count().ToString();
        }
        #endregion
        #region Class Methods
        public static string obtenerEventoClickHtml(Trazabilidad objTrazabilidad)
        {
            string strReturn = "";

            strReturn += "function(point) {";
            strReturn += "$(\"#divTrazabilidadEdit\").show('slide');";
            strReturn += "document.getElementById(\"aTrazabilidadEditCantidadPasos\").innerHTML = '"+objTrazabilidad.obtenerCantidadDePasos()+"';";
            strReturn += "document.getElementById(\"aTrazabilidadEditId\").innerHTML = '" + objTrazabilidad.objPolyline.PolylineID + "';";
            strReturn += "}";
            
            return strReturn;
        }
        #endregion
    }
    #endregion

    #region CLIENTE
    /// <summary>
    /// Cliente es la clase que guarda los datos del usuario
    /// </summary>
    [Serializable()]
    public class Cliente
    {
        int IdUsuario;
        string strUsuario_;
        string strNombre_;
        string strApellido_;
        string strPassword_;
        string strMail_;
        string strPrimaryPhone_;
        string strLatitudCent_;
        string strLongitudCent_;
        Coordenada objPosicionCentral;
        string strEstado_;                
        string strCelular;
        public bool ActivaPorPrimeraVez { get; set; }

        #region Constructor
        public Cliente()
        {
            IdUsuario = 0;
            objPosicionCentral = new Coordenada();
            strEstado_ = null;
        }

        public Cliente(int intIdUsuarioParam, string strLatitudCentralParam, string strLongitudCentralParam)
        {
            IdUsuario = intIdUsuarioParam;
            objPosicionCentral = new Coordenada(strLatitudCentralParam, strLongitudCentralParam);
            strEstado_ = null;
        }
        #endregion
        #region Accessing Protocol
        public int intIdUsuario
        {
            get
            {
                return IdUsuario;
            }
            set
            {
                IdUsuario = value;
            }
        }

        public string strUsuario
        {
            get
            {
                return strUsuario_;
            }
            set
            {
                strUsuario_ = value;
            }
        }

        public string strNombre
        {
            get
            {
                return strNombre_;
            }
            set
            {
                strNombre_ = value;
            }
        }
        public string strApelido
        {
            get
            {
                return strApellido_;
            }
            set
            {
                strApellido_ = value;
            }
        }
        public string strPassword
        {
            get
            {
                return strPassword_;
            }
            set
            {
                strPassword_ = value;
            }
        }
        public string strMail
        {
            get
            {
                return strMail_;
            }
            set
            {
                strMail_ = value;
            }
        }
        public string strPrimaryPhone
        {
            get
            {
                return strPrimaryPhone_;
            }
            set
            {
                strPrimaryPhone_ = value;
            }
        }
        public string strEstado
        {
            get
            {
                return strEstado_;
            }
            set
            {
                strEstado_ = value;
            }
        }
        public string strLatitudCent
        {
            get
            {
                return strLatitudCent_;
            }
            set
            {
                strLatitudCent_ = value;
            }            
        }
        public string strLongitudCent
        {
            get
            {
                return strLongitudCent_;
            }
            set
            {
                strLongitudCent_ = value;
            }            
        }

        public Coordenada obtenerPosicionCentral()
        {
            return objPosicionCentral;
        }

        public void guardarPosicionCentral(Coordenada objPosicionCentralParam)
        {
            objPosicionCentral = objPosicionCentralParam;
        }

        #endregion

        public string getMail()
        {
            return strMail;
        }

        public string getMobile()
        {
            return strCelular;
        }

        public string getPrimaryPhone()
        {
            return strPrimaryPhone;
        }

        public void setPrimaryPhone(string strPrimaryPhoneParam)
        {
            strPrimaryPhone = strPrimaryPhoneParam;
        }

        public void setMail(string strMailParam)
        {
            strMail = strMailParam;
        }

        public void setMobile(string strMobileParam)
        {
            strCelular = strMobileParam;
        }
    }
    #endregion


    [Serializable()]
    public class DatosGPS
    {
        
        public double dbLatitud { get; set; }   //example 34350503  (Latitude XXXX.XXXX)
        public double dbLongitud { get; set; } //example 058262990  (Longitude XXXXX.XXXX)
        public string Email { get; set; }
        public string strImei { get; set; }           //example 354779035057430
        public string strIdCode { get; set; }     //The ID code can be 05*850 or 05*827.
        //05*850 is returned when the unit has received a request message from base to send a location message. 05*827 is returned if any input is activated.  
        public string strStatusCode { get; set; }    //example 000 - Ascii code 0 = 48STATUS CODE:Sent in ASCII code for text message. Add $30 to First, Second and Third Code.
        //; First code:; 1 = Battery power low <20%; 2 = Motion alert alarm; 4 = Park alert alarm; 8 = Entering Sleep mode message; 16 = Temperature from Digital Thermometer (DS18S20) above or below the configured value
        //; Second Code:; 1 = Panic Button Activated; 2 = Motion detection alarm enabled; 4 = Park detection alarm enabled; 8 = 24 Hour no motion alarm activated
        //; Third Code:; 1 = Vehicle traveled above MAX configured speed limit; 2 = AUX1 input activatedPDF created with pdfFactory Pro trial version www.pdffactory.com- 42 -42; 4 = ADC activated; 8 = 0 -> Positive temperature reading; 1 -> Negative temperature reading
        public string strUnitNumber { get; set; }     //PT35 (unit number)
        public string strValidate { get; set; }      //(A o V GPS Validate or non validate)
        public string strSurNor { get; set; }        //(South or north) S or N
        public string strEastWest { get; set; }      //(East or West) E or W
        public string strSpeed { get; set; }      //(Speed  XXX.X) example 0003
        public string strCourse { get; set; }        //example 0564		(Course in degrees)
        public string strHDOP { get; set; }       //example  015		(HDOP Horizontal dilution of precision)
        public string strGPSTimeDate { get; set; }      //042332		(GPS Time hh:mm:ss)      //180911		(GPS Date dd-mm-yy)
        public string strUnitVersion { get; set; }    //124		(unit version x.xx)
        public string strBattery { get; set; }        //99		(BAttery level status 00 a 99%)	
        public string strOtrasFun { get; set; }       //00		(ADC voltage - level houers count aux1 - ibutton id)	Otras funcionalidades.
        public TipoLectura enTipoLecturaDatos;// = new enTipoLectura();     
    }

    #region CABALLO
    /// <summary>
    /// Clase que almacena los datos de los caballos
    /// </summary>
    public class Caballo                                                    //FD 12/3/12
    {
        #region Properties
            public string strNombre_;                                           //FD 12/3/12            
            public Cliente objCliente;                                  //FD 14-8-12
            public Coordenada objPosicion;                                      //FD 12/3/12
            public Equipo objEquipoCaballo;                                 //FD 12/3/12          
            public double dbVelocidadActual;                                //FD 12/3/12
            public List<double> strVelocidadHistorica;                      //FD 12/3/12
            public string strIDCaballo;                                 //FD 12/3/12
            public bool Habilitado;                                  //FD 12/3/12
            public DateTime dtUltimaActualizacion;                       //FD 12/3/12
            public string PathFotoCaballo;                               //FD 12/3/12
            public Trazabilidad objTrazabilidad;            
            
            public RazaCaballo enumRazaCaballo;                            //FD 12/3/12
            public  CategoriaCaballo enumCategoriaCaballo;                  //FD 12/3/12
        #endregion

        #region Constructor
        public Caballo()
        {
            strNombre_ = null;            
            objEquipoCaballo=new Equipo();
            
            objCliente=new Cliente();                                  //FD 14-8-12
            objPosicion = new Coordenada();
        }
        public Caballo(string strNombreParam, string strLatitudParam, string strLongitudParam)
        {
            strNombre_ = strNombreParam;
            objPosicion = new Coordenada();
            objPosicion.strLatitud = strLatitudParam;
            objPosicion.strLongitud = strLongitudParam;
        }
        #endregion

        #region Accessing Protocol
        public string strNombre
        {
            get
            {
                return strNombre_;
            }
            set
            {
                strNombre_ = value;
            }
        }
                
        public void guardarPosicionActual(Coordenada objPosicionActual)
        {
            objPosicion = objPosicionActual;
        }

        

        public Coordenada obtenerPosicionActual()
        {
            return objPosicion;
        } 
        #endregion

        public int getIDRaza()
        {
            RazaCaballo raza;
            int inRaza=1;   //Harcoded  FD v01.01
            return inRaza;
        }
        
        public int getIDCategoria()
        {
            RazaCaballo Categoria;

            int inCategoria=1;  //HARcoded  FD v01.01
            return inCategoria;
        }

        public string getRaza()
        {
            return "Raza hardcoded";
        }

        public string getCategoria()
        {
            return "Categoria hardcoded";
        }

        public string getDisciplina()
        {
            return "Disciplina Hardcoded";
        }

        internal string getEstado()
        {
            return "Estado hardcoded";
        }
    }
    #endregion

    #region RAZACABLLO
    public enum RazaCaballo
    {
        Desconocida = 1
    }
    #endregion

    #region CATEGORIA CABALLO
    public enum CategoriaCaballo
    {
        Desconocida = 1
    }
    #endregion

    #region EQUIPO
    public class Equipo
    {
        #region Properties
           Nullable<int> idDb;
            public  string strSimCodArea;
            public  string strTelefono;
            public DateTime dtFechaInstalacion;                           
            public  int inCantidadDeReparaciones;
            public  Operador enumOperador;
            //public string strIDEquipo;  //CODE ID??
            public int inIDEquipo;  //FD 15-8-12
            public string strCodeID;
            public string strCodeStatus;
            public string strUnitNumber;
            public string strUnitVersion;
            public string strNivelDeBateria;
            public string strOtraFuncionalidad;
            public string strIMEI;
            
        #endregion

            public bool nivelDeBateriaDebajoDeUmbral()
            {
                ///TODO: HAcer el procesamiento de bateria
                return true;
            }

            public string obtenerNivelDeBateria()
            {
                return "45%";
            }

            public Equipo armarObjEquipo(DatosGPS objDatosGPS_Equipo,Equipo objEquipo)  //En el caso de que se quiera actualizar equipo desde datos gps FD 15-8-12
            { 
                try
                {
                    /*
                    objEquipo.strSimCodArea=;
                    objEquipo.strTelefono=;
                    objEquipo.dtFechaInstalacion=;
                    objEquipo.inCantidadDeReparaciones=;
                    objEquipo.enumOperador=;
                    objEquipo.strIDEquipo=;
                    objEquipo.strCodeStatus=;        
                    objEquipo.strUnitNumber=objDatosGPS_Equipo.strUnitNumber;
                    objEquipo.strUnitVersion=objDatosGPS_Equipo.strUnitVersion;
                    objEquipo.strNivelDeBateria=objDatosGPS_Equipo.strBattery;
                    objEquipo.strOtraFuncionalidad=objDatosGPS_Equipo.strOtrasFun;
                    objEquipo.strIMEI=objDatosGPS_Equipo.strImei;
                     * */
                }catch(Exception ex)
                {
                    throw ex;
                }

                return objEquipo;
            }
    }
    #endregion

    #region COORDENADA
    public class Coordenada
    {
        #region Properties
        GLatLng _objCoordinate;
        public string strLatitud
        {
            get
            {
                return _objCoordinate.lat.ToString();
            }
            set
            {
                try
                {

                    _objCoordinate.lat = Convert.ToDouble(value.Replace('.', ','));
                }
                catch (Exception ex)
                {
                    ControlLog.writeLog("[Coordenadas::strLatitud::set]: Excepcion cargando latitud = " + value + ": " + ex.Message);
                    _objCoordinate.lat = 0;
                }

            }
        }
        public string strLongitud
        {
            get
            {
                return _objCoordinate.lng.ToString();
            }
            set
            {
                try
                {
                    _objCoordinate.lng = Convert.ToDouble(value.Replace('.', ','));
                }
                catch (Exception ex)
                {
                    ControlLog.writeLog("[Coordenadas::strLongitud::set]: Excepcion cargando longitud = " + value + ": " + ex.Message);
                    _objCoordinate.lng = 0;
                }

            }
        }
        #endregion

        public Coordenada()
        {
            _objCoordinate = new GLatLng();
        }

        public Coordenada(string strLatitudCentralParam, string strLongitudCentralParam)
        {
            // TODO: Complete member initialization
            _objCoordinate = new GLatLng();
            try
            {
                this._objCoordinate.lat = Convert.ToDouble(strLatitudCentralParam);
                this._objCoordinate.lng = Convert.ToDouble(strLongitudCentralParam);                
            }
            catch(Exception ex)
            {
                ControlLog.writeLog("[ctor:Coordenada] Excepcion cargando coordenadas: " + strLatitudCentralParam + " - " + strLongitudCentralParam + " Mensaje: " + ex.Message);
            }
        }

        #region Methods
        public GLatLng getLatLng()
        {
            return _objCoordinate;
        }
        #endregion

    }
    #endregion

    #region GEOFENCE
    public class GeoFence
    {
        #region Properties
        public GPolygon objPolygon;
        public GLatLng objCoordenadaDeReferenciaInterna;
        public string strDescripcion { get; set; }
        public string strIdGeoFence { get; set; }
        public int intIdCliente { get; set; }
        public string strIdPoligono { get; set; }
        private bool _boolInitialized;
        public string strArea { get; set; }
        #endregion

        #region Constructor
        public GeoFence()
        {
            _boolInitialized = false;
            List<GLatLng> lstPolygonBounds = new List<GLatLng>();
            objCoordenadaDeReferenciaInterna = new GLatLng(0, 0); //Se centra en cualquier lado, queda a responsabilidad del que crea el GeoFence de marcar la referencia.
            objPolygon = new GPolygon();
            objPolygon.fillColorNet = Color.DarkOrange;
            objPolygon.fillOpacity = 0.4;
            objPolygon.clickable = true;          
        }

        #endregion

        public void AddCoordinates(string strLatitud, string strLongitud)
        {
            try
            {

                GLatLng objLatLng = new GLatLng(Convert.ToDouble(strLatitud.Replace('.', ',')), Convert.ToDouble(strLongitud.Replace('.', ',')));
                objPolygon.points.Add(objLatLng);
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[addCordinates] Excepcion agregando coordenadas (" + strLatitud.Replace('.', ',') + " - " + strLongitud.Replace('.', ',') + "):" + ex.Message);
            }
        }

        public void AddInfo(string strIdClienteParam, string strDescripcionParam, string strIdGeoFenceParam)
        {
            try
            {
                if (_boolInitialized == false)
                {
                    strDescripcion = strDescripcionParam;
                    intIdCliente = Convert.ToInt32(strIdClienteParam);
                    strIdGeoFence = strIdGeoFenceParam;
                    _boolInitialized = true;
                }
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[addInfo] Excepcion agregando info: " + ex.Message);
            }
        }

        public void DibujarEn(GMap GMap1,IPolygonAction interfaceAccion, bool boolDibujable,bool boolEditable)
        {
            try
            {
                List<GLatLng> lstStartPoint = new List<GLatLng>();
                lstStartPoint.Add(GMap1.GCenter);
                GPolygon objNewPolygon = new GPolygon(lstStartPoint, Color.DarkOrange, 0.4);
                this.objPolygon = objNewPolygon;
                this.objPolygon.enableDrawing = boolDibujable;
                this.objPolygon.enableEditing = boolEditable;
                this.objPolygon.clickable = true;


                GMap1.addPolygon(this.objPolygon);
                GMap1.addListener(interfaceAccion.agregarEvento(this));
                //GMap1.addListener(new GListener(this.objPolygon.PolygonID, GListener.Event.click, "function(point) {if(confirm('¿Desea guardar este GeoFence?')){ var ev = new serverEvent('saveGeoFence', subgurim_GMap1); ev.addArg(this.getVertexCount()); ev.addArg('" + this.objPolygon.PolygonID + "');  ev.addArg(this.getArea()); var i=0; for(i=0;i<this.getVertexCount();i++) { ev.addArg(this.getVertex(i));}  ev.send(); alert('GeoFence guardado OK!');}else{alert('GeoFence sin guardar, se borrará automáticamente en la próxima actualización');}}"));
            }
            catch (Exception ex)
            {
                ControlLog.writeLog("[dibujarEn] Excepcion dibujando GeoFence: " + ex.Message);
            }
        }

        public string getArea()
        {
            return "22.23234";
        }

        public string getCantidadCaballos()
        {
            return "2";
        }

     
    }
    #endregion

    #region GEOCHECKPOINT
    public class GeoCheckPoint
    {
        #region Properties
        private GPolyline objPolyLine;
        public string strDescripcion;
        #endregion

        #region Constructor 
        public GeoCheckPoint()
        {
           
        }
        #endregion

        #region Methods

        public List<GLatLng> obtenerTrazaPorCoordenadas()
        {
            return objPolyLine.points;
        }

        public void DibujarEn(GMap GMap1)
        {
            List<GLatLng> lstStartPoint = new List<GLatLng>();
            lstStartPoint.Add(GMap1.GCenter);

            this.objPolyLine = new GPolyline(lstStartPoint, Color.Blue, 1, 0.6);         
            GMap1.addPolyline(this.objPolyLine);
        }
        #endregion
    }
    #endregion

    #region Eventos sobre Poligonos

    public interface IPolygonAction
    {
        #region Methods
        GListener agregarEvento(GeoFence objPolygon);
        GListener agregarEvento(Trazabilidad objPolygon);
        #endregion
    }

    public class PolygonActionCreate : IPolygonAction
    {
        #region Methods
        public GListener agregarEvento(GeoFence objPolygon)
        {

            ControlLog.writeLog("[agregarEvento:Create]: Agregando evento ");
       //     GListener objListener = new GListener(objPolygon.objPolygon.PolygonID, GListener.Event.click, "function(point) {if(confirm('¿Desea guardar este GeoFence?')){ var ev = new serverEvent('saveGeoFence', subgurim_GMap1); ev.addArg(this.getVertexCount()); ev.addArg('" + objPolygon.objPolygon.PolygonID + "');  ev.addArg(this.getArea()); var i=0; for(i=0;i<this.getVertexCount();i++) { ev.addArg(this.getVertex(i));}  ev.send(); alert('GeoFence guardado OK!');}else{alert('GeoFence sin guardar, se borrará automáticamente en la próxima actualización');}}");
            GListener objListener = new GListener(objPolygon.objPolygon.PolygonID, GListener.Event.click, "function(point) { $(\"#divGeoFenceCreate\").show(600); document.getElementById(\"aGeoFenceCreateArea\").innerHTML  = this.getArea(); document.getElementById(\"aGeoFenceCreateIdPoligono\").innerHTML  = '"+objPolygon.objPolygon.PolygonID+"'; document.getElementById(\"aGeoFenceCreateArea\").innerHTML  = this.getArea(); document.getElementById(\"aGeoFenceCreateVertexCount\").innerHTML  = this.getVertexCount(); var i=0; for(i=0;i<this.getVertexCount();i++) { document.getElementById(\"aGeoFenceCreateVertexArray\").innerHTML  += this.getVertex(i)+'&';} }");
                                                                                                                                   
            return objListener;
        }

        public GListener agregarEvento(Trazabilidad objPolygon)
        {

            ControlLog.writeLog("[agregarEvento:Create]: Agregando evento ");
            GListener objListener = new GListener(objPolygon.getTraza().PolylineID, GListener.Event.click, Trazabilidad.obtenerEventoClickHtml(objPolygon));

            return objListener;
        }
        #endregion
    }



    public class PolygonActionShow : IPolygonAction
    {
        #region Methods
        public GListener agregarEvento(GeoFence objPolygon)
        {
            ControlLog.writeLog("[agregarEvento:Show]: Agregando evento ");
            //GListener objListener = new GListener(objPolygon.objPolygon.PolygonID, GListener.Event.click, "function(point) { $(\"#divGeoFenceInfo\").show(600); document.getElementById(\"aGeoFenceArea\").innerHTML  = '" + objPolygon.getArea() + "'; document.getElementById(\"aGeoFenceDescripcion\").innerHTML  = '" + objPolygon.strDescripcion + "'; document.getElementById(\"aGeoFenceCaballosDentro\").innerHTML  = '" + objPolygon.getCantidadCaballos() + "';}");
            GListener objListener = new GListener(objPolygon.objPolygon.PolygonID, GListener.Event.click, "function(point) { $(\"#divGeoFenceInfo\").show(600); document.getElementById(\"aGeoFenceArea\").innerHTML  = '" + objPolygon.getArea() + "'+'m2'; document.getElementById(\"aGeoFenceDescripcion\").innerHTML  = '" + objPolygon.strDescripcion + "'; document.getElementById(\"aGeoFenceCaballosDentro\").innerHTML  = '" + objPolygon.getCantidadCaballos() + "';  document.getElementById(\"aGeoFenceId\").innerHTML  = '" + objPolygon.strIdGeoFence + "';}");
            return objListener;
        }
        public GListener agregarEvento(Trazabilidad objPolygon)
        {

            ControlLog.writeLog("[agregarEvento:Create]: Agregando evento ");
            GListener objListener = new GListener(objPolygon.getTraza().PolylineID, GListener.Event.click, Trazabilidad.obtenerEventoClickHtml(objPolygon));

            return objListener;
        }
        #endregion
    }

#endregion

    #region Alertas
    [Serializable()]
    public class Alerta
    {
        public string strMensaje { get; set; } 
        public string strModoAlerta { get; set; } 
        public string strIdAlerta { get; set; } 

        

        public Alerta()
        {
            
        }

        public void setMensajeAlerta(string strMensajeAlertaParam)
        {
            strMensaje = strMensajeAlertaParam;
        }

        public void setModoAlerta(string strModoAlertaParam)
        {
              strModoAlerta = strModoAlertaParam;
        }

        public void setIdAlerta(string strIdAlertaParam)
        {
            strIdAlerta = strIdAlertaParam;
        } 
   
           

        public string getMensajeAlerta()
        {
            return strMensaje;
        }
        public string getModoAlerta()
        {
            return strModoAlerta;
        }

        public string getIdAlerta()
        {
            return strIdAlerta;
        }
    }


   

    public class Evento 
    {
        protected TipoEvento objTipoEvento;
        protected Caballo objCaballo;
        protected Cliente objCliente;

        public Evento(Caballo objCaballoInvolucradoParam, TipoEvento objTipoEventoParam, Cliente objClienteParam)
        {
            objTipoEvento = objTipoEventoParam;
            objCaballo = objCaballoInvolucradoParam;
            objCliente = objClienteParam;

            objTipoEventoParam.procesar(objCaballo, objCliente);

        }
        public override string ToString()
        {
            string strResultado = objCaballo.strNombre + "(" + objCaballo.strIDCaballo + "): " + objTipoEvento.getAlert();

            return strResultado;
        }
        public string getAlertMode()
        {
            switch (objTipoEvento.getAlertVia())
            {
                case enumModoDeAlertaDeEvento.Mail:
                    return "MAIL:" + objCliente.getMail();
                   
                case enumModoDeAlertaDeEvento.SMS:
                    return "SMS:" + objCliente.getMobile();
                    
                case enumModoDeAlertaDeEvento.Telefono:
                    return "PHONE:" + objCliente.getPrimaryPhone();
                    
                default:
                    return "";
                    
            }
        }
        public string obtenerIdRemitente()
        {
            return objCaballo.strIDCaballo;
        }
        public string obtenerIdEvento()
        {
            return objTipoEvento.getIdDb();
        }
        public string obtenerMensaje()
        {
            return objTipoEvento.obtenerMensaje();
        }
    }


    public interface IEvento
    {
        IEvento procesar(Caballo objCaballo, Cliente objCliente, TipoEvento objTipoEventoInvocador);
    }


    public class EventoComenzarProcesamiento : IEvento
    {
        public IEvento procesar(Caballo objCaballo, Cliente objCliente, TipoEvento objTipoEventoInvocador)
        {
            ControlLog.writeLog("[EventoComenzarProcesamiento:procesar] Comenzando la cadena de procesamientos de eventos posibles");
            return new EventoGeoFence();
        }
    }
    public class EventoGeoFence : IEvento
    {
        public IEvento procesar(Caballo objCaballo, Cliente objCliente, TipoEvento objTipoEventoInvocador)
        {
            if (objTipoEventoInvocador.obtenerDescripcion().StartsWith("(GEOFENCE:0)"))
            {
                ControlLog.writeLog("[EventoGeoFence:procesar] Procesando eventuales alertas de GEOFENCE:0...");

                try
                {
                    ControlDB objConnection = new ControlDB();

                    foreach (GeoFence objGeoFence in objConnection.obtenerGeoFences(objCliente.intIdUsuario))
                    {
                        if (ControlGeografico.estaCaballoDentroDeGeofence(objCaballo, objGeoFence))
                        {
                            objTipoEventoInvocador.agregarAlerta(objCaballo.strNombre + " esta afuera del Geofence \"" + objGeoFence.strDescripcion + "\"");

                        }
                    }
                }
                catch(Exception ex)
                {
                    ControlLog.writeLog("[EventoGeoFence:procesar] Excepcion procesando: "+ex.Message);
                    throw ex;
                }
             

                
                return null;
            }
            else
            {
                return new EventoCheckPoint();
            }
            
        }
    }
    public class EventoCheckPoint : IEvento
    {
        public IEvento procesar(Caballo objCaballo, Cliente objCliente, TipoEvento objTipoEventoInvocador)
        {
            if (objTipoEventoInvocador.obtenerDescripcion().StartsWith("(GEOCHECKPOINT:0)"))
            {
                ControlLog.writeLog("[EventoCheckPoint:procesar] Procesando eventuales alertas de GeoCheckPoint:0...");
                try
                {
                    ControlDB objConnection = new ControlDB();
                  
                  foreach (GeoCheckPoint objGeoCheckPoint in objConnection.obtenerGeoCheckPoint(objCliente.intIdUsuario))
                    {
                        if (ControlGeografico.pasaCaballoPorCheckPoint(objCaballo, objGeoCheckPoint))
                        {
                            objTipoEventoInvocador.agregarAlerta(objCaballo.strNombre + " cruzó el GeoCheckPoint \"" + objGeoCheckPoint.strDescripcion + "\"");

                        }
                    }
                }
                catch (Exception ex)
                {
                    ControlLog.writeLog("[EventoCheckPoint:procesar] Excepcion procesando: " + ex.Message);
                    throw ex;
                }
             
                return null;
            }
            else
            {
                return new EventoBateriaBaja();
            }

        }
    }
    public class EventoBateriaBaja : IEvento
    {
        public IEvento procesar(Caballo objCaballo, Cliente objCliente, TipoEvento objTipoEventoInvocador)
        {
            if (objTipoEventoInvocador.obtenerDescripcion().StartsWith("(LOWBATTERY:0)"))
            {
                ControlLog.writeLog("[EventoBateriaBaja:procesar] Procesando eventuales alertas de bateria baja:0...");
                try
                {
                    if (objCaballo.objEquipoCaballo.nivelDeBateriaDebajoDeUmbral())
                    {
                        objTipoEventoInvocador.agregarAlerta("El collar de "+objCaballo.strNombre + " tiene la bateria baja "+objCaballo.objEquipoCaballo.obtenerNivelDeBateria());
                    }
                }
                catch (Exception ex)
                {
                    ControlLog.writeLog("[EventoBateriaBaja:procesar] Excepcion procesando: " + ex.Message);
                    throw ex;
                }
                return null;
            }
            else
            {
                /// Solo debe tirar la excepcion en el ultimo nodo de implementacion
                throw new Exception("Para el TipoEvento invocador (Descripcion = " + objTipoEventoInvocador.obtenerDescripcion() + "), siendo esta la ultima implementacion disponible, se informa que no hay implementacion de proceso para este tipo de evento");   
                return null;
            }

        }
    }


    public class TipoEvento
    {

        private string strDescripcion;
        private int intIdDb;
        private enumModoDeAlertaDeEvento enumModoDeAlertaDeEvento;
        private string strMensajeAMostrar;
        private List<string> lstAlertas;
        
        public TipoEvento(string strDescripcionParam,string strMensajeAMostrarParam, int intIdDbParam)
        {
            strDescripcion = strDescripcionParam;
            intIdDb = intIdDbParam;
            strMensajeAMostrar = strMensajeAMostrarParam;
            lstAlertas = new List<string>();
        }

        public void procesar(Caballo objCaballo,Cliente objCliente)
        {
            try
            {
            IEvento objProcesador;
            objProcesador = new EventoComenzarProcesamiento();
            ControlLog.writeLog("[procesar] Comenzando Procesamiento");
            while ((objProcesador = objProcesador.procesar(objCaballo,objCliente,this)) != null) ;
            ControlLog.writeLog("[procesar] Procesamiento finalizado OK");  
            }
            catch(Exception ex)
            {
                ControlLog.writeLog("[procesar] Excepcion procesando eventos: "+ex.Message);       
                throw ex;
            }

        }
        
        public string getAlert()
        {
            return strMensajeAMostrar;
        }

        public enumModoDeAlertaDeEvento getAlertVia()
        {
            return enumModoDeAlertaDeEvento;
        }

        public string getIdDb()
        {
            return intIdDb.ToString();
        }

        public string obtenerMensaje()
        {
            string strAlertasEncontradas="";
            foreach (string strAlertaIndividual in lstAlertas)
            {
                strAlertasEncontradas += ":: -> " + strAlertaIndividual;
            }
            return strMensajeAMostrar + " - Alertas encontradas " + strAlertasEncontradas;
        }

        public string obtenerDescripcion()
        {
            return strDescripcion;
        }

        public void agregarAlerta(string strAlertaParam)
        {
            lstAlertas.Add(strAlertaParam);
        }
    }

    public enum enumModoDeAlertaDeEvento
    {
        Mail,
        SMS,
        Telefono,
    }
    #endregion

    
}



public enum TipoLectura
{
    Gps=0,
    Gsm=1
}
